# Ultralytics YOLO 🚀, AGPL-3.0 license

from predictor.base_predictor import BasePredictor
from predictor.ops import non_max_suppression
from ultralytics.engine.results import Results
from ultralytics.utils import ops


class DetectionPredictor(BasePredictor):
    """
    A class extending the BasePredictor class for prediction based on a detection model.

    Example:
        ```python
        from ultralytics.utils import ASSETS
        from ultralytics.models.yolo.detect import DetectionPredictor

        args = dict(model='yolov8n.pt', source=ASSETS)
        predictor = DetectionPredictor(overrides=args)
        predictor.predict_cli()
        ```
    """

    def postprocess(self, preds, img, orig_imgs, orig_imgs_l=None):
        """Post-processes predictions and returns a list of Results objects."""
        preds = non_max_suppression(
            preds,
            self.args.conf,
            self.args.iou,
            agnostic=self.args.agnostic_nms,
            max_det=self.args.max_det,
            classes=self.args.classes,
        )

        if not isinstance(orig_imgs, list):  # input images are a torch.Tensor, not a list
            orig_imgs = ops.convert_torch2numpy_batch(orig_imgs)

        results = []
        for i, pred in enumerate(preds):
            orig_img = orig_imgs[i]
            pred[:, :4] = ops.scale_boxes(img.shape[2:], pred[:, :4], orig_img.shape)
            # 【兼容】 将框大小x1,y1,x2,y2比例变换为目标图片大小的值
            if orig_imgs_l:
                orig_img_l = orig_imgs_l[i]
                orig_img_shape = orig_img.shape
                orig_img_l_shape = orig_img_l.shape
                wight_rate = orig_img_l_shape[1] / orig_img_shape[1]
                height_rate = orig_img_l_shape[0] / orig_img_shape[0]
                pred[:, 0], pred[:, 2] = pred[:, 0] * wight_rate, pred[:, 2] * wight_rate
                pred[:, 1], pred[:, 3] = pred[:, 1] * height_rate, pred[:, 3] * height_rate
            orig_img_l = orig_imgs_l[i] if orig_imgs_l else orig_img
            #
            img_path = self.batch[0][i]
            results.append(Results(orig_img_l, path=img_path, names=self.model.names, boxes=pred))
        return results
